<script setup>
import floatBall from "@/components/FloatBall.vue"
import bubble from '@/components/AIBubble.vue'
import { currentNote, currentUser  } from "../global"
import { globalEventBus } from '@/util/eventBus'
import EditorMenu from './EditorMenu.vue'

import { getNoteAPI, updateNoteAPI } from '@/api/note.js'
import {ElMessage} from "element-plus";
import StarterKit from '@tiptap/starter-kit';
import { defineComponent, onMounted, onBeforeUnmount, ref,watch, computed } from 'vue';

import { Editor, EditorContent, useEditor, BubbleMenu  } from '@tiptap/vue-3';

import ListItem from '@tiptap/extension-list-item'
import OrderedList from '@tiptap/extension-ordered-list'
import BulletList from '@tiptap/extension-bullet-list'

import CodeBlockLowlight from '@tiptap/extension-code-block-lowlight'
import css from 'highlight.js/lib/languages/css'
import js from 'highlight.js/lib/languages/javascript'
import ts from 'highlight.js/lib/languages/typescript'
import html from 'highlight.js/lib/languages/xml'
import { common, createLowlight } from 'lowlight'
const lowlight = createLowlight()
lowlight.register({ html, ts, css, js })
// 字数统计
import Placeholder from '@tiptap/extension-placeholder'

import TaskItem from '@tiptap/extension-task-item'
import TaskList from '@tiptap/extension-task-list'
import Table from '@tiptap/extension-table'
import TableCell from '@tiptap/extension-table-cell'
import TableHeader from '@tiptap/extension-table-header'
import TableRow from '@tiptap/extension-table-row'
import Text from '@tiptap/extension-text'

import { Extension } from '@tiptap/core'

import { streamPolishAPI, streamGenerateTableAPI, streamGetAbstractAPI, streamGetExpandAPI, streamGetSegmentAPI, streamTranslateAPI } from '@/api/ai';

// 
document.addEventListener('mousedown', function(event) {
    
    // if (!contextMenuVisible.value || clickedTarget == 'content' || clickedTarget == 'contentDisplayer' || clickedTarget == 'item' || clickedTarget == 'content') {
    //   return
    // }
    // if ($(event.target).closest(".contextmenu").length > 0) {
    //   return
    // }
    
  
    console.log('hide')
    console.log($(event.target).closest(".contextmenu"))
    console.log(event.target)

    mouseDownHideContextMenu()
    
    
});

const aiText = ref('')
const editButtonVisible = ref(false)

var currentFrom = 0
var currentTo = 0

const noteInEditor = ref({
    notebookId: -1,
    noteId: -1,
    name: ""
})

const CustomExtension = Extension.create({
    addCommands: () => {
        return {
            getSelectedText: () => ({ editor }) => {
                const { from, to, empty } = editor.state.selection
                currentFrom = from
                currentTo = to
                if (empty) {
                    return ''
                }

                return editor.state.doc.textBetween(from, to, ' ')
            },
            
        }
    },
})

const editor = new Editor({
        content: ``,
        extensions: [
          StarterKit,
          TaskList,
          TaskItem,
          Placeholder.configure({
            placeholder: '开始输入文本 …'
          }),
          OrderedList,
          BulletList,
          ListItem,
          CustomExtension,
          // Document,
          // Paragraph,
          Text,
          // Gapcursor,
          Table.configure({
            resizable: true,
          }),
          TableRow,
          TableHeader,
          TableCell,
        ],
        injectCSS: false
      })

const imageUploadURL = 'http://localhost:8081/upload/photo'

const showBubble = ref(false)

var currentSelectedText = ''

var showContextMenuCounter = 0
const showContextMenuRepeatTimes = 20

const func = ref('')

const position = ref({
  top: 0,
  left: 0
})

const contextMenuVisible = ref(false)

function mouseDownHideContextMenu() {
  //alert('close')
  currentSelectedText = ''
  aiText.value = ''
  //window.getSelection().removeAllRanges()
  contextMenuVisible.value = false
  editButtonVisible.value = false
}

function keyDownHideContextMenu() {
  currentSelectedText = ''
  aiText.value = ''
  contextMenuVisible.value = false
  editButtonVisible.value = false
}

function scrollToBottom() {
  var scrollBox = document.getElementById('scrollable');
  scrollBox.scrollTop = scrollBox.scrollHeight - scrollBox.clientHeight;
}

function showContextMenu() {
  currentSelectedText = editor.commands.getSelectedText()
  
  if(currentSelectedText !== ''){
    var rect = window.getSelection().getRangeAt(0).getBoundingClientRect();
    
    position.value.top =  rect.bottom
    position.value.left = rect.left

    if (showContextMenuCounter > showContextMenuRepeatTimes) {
      showContextMenuCounter = 0
    }
    else 
    {
      if (showContextMenuCounter == 0) {
        contextMenuVisible.value = true
      }
      showContextMenuCounter++
      setTimeout(showContextMenu, 10)
    }
  }
  else {
    mouseDownHideContextMenu()
  }
}



function reset() {
  showBubble.value = false
}

function insert(content) {
    if (editor) {
        editor.commands.insertContent(content)
    }
}

function saveNote() {
  console.log('saveNote')
    var note = noteInEditor.value
    note.content = editor.getMarkdown()
    updateNoteAPI(note)
        .catch((err) => console.log(err))
}

function replace(content) {
    if (editor) {
      editor.commands.insertContentAt({currentFrom, currentTo}, content, {
        updateSelection: true
      })
    }
    mouseDownHideContextMenu()
}

function setTextBuffer(msg) {
    //console.log(msg)
    aiText.value = msg;  
    scrollToBottom()
}

function errorHandler(err) {
        console.log(err)
        //aiText.value = err.response.data.error
}
    

function abstract(text) {
  
  streamGetAbstractAPI()
            .withDataHandler((msg) => { setTextBuffer(msg) })
            .withErrorHandler((err) => { errorHandler(err) })
            .withEndHandler(() => {editButtonVisible.value = true})
            .send(text)
}

function poish(text) {
  streamPolishAPI()
            .withDataHandler((msg) => { setTextBuffer(msg) })
            .withErrorHandler((err) => { errorHandler(err) })
            .withEndHandler(() => {editButtonVisible.value = true})
            .send(text)
}

function segment(text) {
  streamGetSegmentAPI()
            .withDataHandler((msg) => { setTextBuffer(msg) })
            .withErrorHandler((err) => { errorHandler(err) })
            .withEndHandler(() => {editButtonVisible.value = true})
            .send(text)
}

function expand(text) {

  streamGetExpandAPI()
            .withDataHandler((msg) => { setTextBuffer(msg) })
            .withErrorHandler((err) => { errorHandler(err) })
            .withEndHandler(() => {editButtonVisible.value = true})
            .send(text)
}


function table(text) {

  streamGenerateTableAPI()
            .withDataHandler((msg) => { setTextBuffer(msg) })
            .withErrorHandler((err) => { errorHandler(err) })
            .withEndHandler(() => {editButtonVisible.value = true})
            .send(text)
            
}


function translate(text) {

  streamTranslateAPI()
            .withDataHandler((msg) => { setTextBuffer(msg) })
            .withErrorHandler((err) => { errorHandler(err) })
            .withEndHandler(() => {editButtonVisible.value = true})
            .send(text)
  
}

function cancel() {
  mouseDownHideContextMenu()
}

function setBubble(AIFunction, select) {
  const floatBall = document.getElementById("ball");
  const bubble = document.getElementById("bubble");
  const ballTop = floatBall.offsetTop;
  const ballLeft = floatBall.offsetLeft;
  // 让ai-bubble出现在float-ball左上方
  bubble.style.top = ballTop + "px";
  bubble.style.left = ballLeft + "px";
  func.value = AIFunction
  selectedText.value = select
  showBubble.value = true
  // 通知ai对话框关闭
  globalEventBus.emit("AIBubbleOpen");
}

watch(() => currentNote.value.noteId, (note, prevNote) => {
    console.log(note)
    if (prevNote > 0 && note === -1) {
      editor.clear()
      noteInEditor.value = { notebookId: -1, noteId: -1, name: ""}
      return
    }
      
    if (note === -1)
        return
    if (noteInEditor.value.noteId !== -1) {
        noteInEditor.value.content = editor.getMarkdown()
        updateNoteAPI(noteInEditor.value).then().catch((err) => console.log(err))
    }
    getNoteAPI(note)
        .then((note) => {
            if (editor) {
                editor.setMarkdown(note.content)
                noteInEditor.value = note
            }
        })
        .catch((err) => console.log(err))
},
{
    immediate: true
})

function empty() {
  
}

onMounted(() => {
  var loadContent = '<h4>两行三列:</h4>\
<table border="1">\
<tr>\
  <td>100</td>\
  <td>200</td>\
  <td>300</td>\
</tr>\
<tr>\
  <td>400</td>\
  <td>500</td>\
  <td>600</td>\
</tr>\
</table>'
  if (currentNote.value.noteId !== -1) {
      getNoteAPI(currentNote.value.noteId)
      .then((note) => {
          loadContent = note.content.toString()
          noteInEditor.value = note
      })
      .catch((err) => console.log(err))
  }
  console.log(editor)
  console.log(editor.commands)
  editor.commands.setContent(loadContent)
});


onBeforeUnmount(() => {
  globalEventBus.all.clear()
  if (noteInEditor.value.noteId !== -1) {
    saveNote()
  }
  editor?.destroy();
})

</script>

<template>
  <div v-show="contextMenuVisible" :style="{ left: position.left + 'px', top: position.top + 'px', display: (contextMenuVisible ? 'block' : 'none') }" class="contextmenu">
      <div class="buttonGroup">
        <div class="item" @mousedown.prevent="abstract(currentSelectedText)">
            概括
        </div>
        <div class="item" @mousedown.prevent="expand(currentSelectedText)">
            续写
        </div>
        <div class="item" @mousedown.prevent="translate(currentSelectedText)">
            翻译
        </div>
        <div class="item" @mousedown.prevent="table(currentSelectedText)">
            表格
        </div>
        <div class="item" @mousedown.prevent="segment(currentSelectedText)">
            分段
        </div>
        <div class="item" @mousedown.prevent="polish(currentSelectedText)">
            润色
        </div>
      </div>
      <div class="contentDisplayer" @mouseup="showContextMenu">
          <div class="content" id="scrollable" @mousedown.prevent="empty()">
          {{ aiText }}
          </div>
      </div>
      <div class="buttonGroup" v-show="editButtonVisible">
        <div class="item" @click="insert(aiText)">
            插入
        </div>
        <div class="item" @click="replace(aiText)">
            替换
        </div>
        <div class="item" @click="cancel()">
            取消
        </div>
        
      </div>
  </div>

    <div class="editor">
      <div class="editor-card">
        
        <div class="top-tools">
          <EditorMenu :editor="editor" />
        </div>
        <div class="edit-cont">
          <EditorContent
            style="padding: 8px; "
            @mouseup="showContextMenu"
            @keydown="keyDownHideContextMenu"
            :editor="editor"
            />
        </div>
        <!--<div class="bottomcount"></div>-->
      </div>
    </div>
 

</template>

<style>
  /* #editor {
    height: 100% !important;
    width: 100% !important;
    margin: 0;
    box-sizing: border-box;
    border: 0;
  } */

</style>

<style scoped>

.content {
  width: 98%;
  height: 100%;
  word-wrap: break-word;
  overflow-y: scroll;
  max-height: 400px;
  scrollbar-width: thin;
  
}

.buttonGroup {
  position: relative;
  height: 100%;
  width: 100%;
  background-color: white;
  display: flex;
}
.contentDisplayer {
  position: relative;
  padding: 5px;
  box-sizing: border-box;
  max-height: 500px;
  height: 100%;
  width: 100%;
  background-color: white;
}

.contextmenu {
     width: 180px;
     margin: 0;
     background: #fff;
     z-index: 3000;
     position: absolute;
     list-style-type: none;
     border-radius: 4px;
     font-size: 12px;
     font-weight: 400;
     color: #333;
     box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.3);
     display: flex;
     flex-direction: column;
     .item {
       height: 35px;
       width:100%;
       line-height: 35px;
       color: rgb(29, 33, 41);
       cursor: pointer;
       text-align: center;
     }
     .item:hover {
       background: rgb(229, 230, 235);
     }
   }

.EditMain{
    position: relative;
    width:100%;
    height: 100%;

    display: grid;
    grid-template-columns: 100%;
  
  }
 

  .editor-card{
    position: relative;
    width:95%;
    height: 95%;
    left: 2.5%;
    top:2.5%;
    display: grid;
    grid-template-rows: 5% 92% 3%;
    /*border: 1px solid #4f5c5765;*/
  }
  .editor-card .editor{
    position: relative;
    width:100%;
    height: 100%;
    left: 0;
    top:0;
    display: grid;
    grid-template-rows: 10% 90%;
  
  }

  .top-tools{
    background-color: rgba(255, 255, 255, 0.199);
    /*border-bottom: 1px dashed #9ca19f65;*/
    
  }
  .bottom-count{
    background-color: rgba(207, 220, 245, 0.199);
    border-top: 1px dashed #9ca19f65;
    height: 100%;
    width: 100%;
    display: grid;
    grid-template-columns: 100%;
    grid-template-rows: 100%;
    justify-items: center;
    align-items: center;
  }
  .edit-cont{
    position: relative;
    width: 100%;
    height: 100%;
    overflow-y: scroll;
  }
  </style>
  <style>
  b {
    font-weight: bold;
  }
  /*
  .ProseMirror {
    overflow-y: scroll;
  }
  */
  .ProseMirror p {
    margin: 0;
  }
  .ProseMirror:focus {
    outline: none;
  }
  .tiptap p.is-editor-empty:first-child::before {
    color: #adb5bd;
    content: attr(data-placeholder);
    float: left;
    height: 0;
    pointer-events: none;
  }
  
  .tiptap {
    > * + * {
      margin-top: 0.75em;
    }
  
    ul {
      padding: 0 2rem;
      list-style: square;
    }
    ol {
      padding: 0 2rem;
      list-style: decimal;
    }
    table {
      border-collapse: collapse;
      table-layout: fixed;
      width: 100%;
      margin: 0;
      overflow: hidden;
  
      td,
      th {
        min-width: 1em;
        border: 2px solid #ced4da;
        padding: 3px 5px;
        vertical-align: top;
        box-sizing: border-box;
        position: relative;
  
        > * {
          margin-bottom: 0;
        }
      }
  
      th {
        font-weight: bold;
        text-align: left;
        background-color: #f1f3f5;
      }
  
      .selectedCell:after {
        z-index: 2;
        position: absolute;
        content: '';
        left: 0;
        right: 0;
        top: 0;
        bottom: 0;
        background: rgba(200, 200, 255, 0.4);
        pointer-events: none;
      }
  
      .column-resize-handle {
        position: absolute;
        right: -2px;
        top: 0;
        bottom: -2px;
        width: 4px;
        background-color: #adf;
        pointer-events: none;
      }
  
      p {
        margin: 0;
      }
    }
    pre {
      background: #0d0d0d;
      color: #fff;
      font-family: 'JetBrainsMono', monospace;
      padding: 0.75rem 1rem;
      border-radius: 0.5rem;
  
      code {
        color: inherit;
        padding: 0;
        background: none;
        font-size: 0.8rem;
      }
  
      .hljs-comment,
      .hljs-quote {
        color: #616161;
      }
  
      .hljs-variable,
      .hljs-template-variable,
      .hljs-attribute,
      .hljs-tag,
      .hljs-name,
      .hljs-regexp,
      .hljs-link,
      .hljs-name,
      .hljs-selector-id,
      .hljs-selector-class {
        color: #f98181;
      }
      .hljs-number,
      .hljs-meta,
      .hljs-built_in,
      .hljs-builtin-name,
      .hljs-literal,
      .hljs-type,
      .hljs-params {
        color: #fbbc88;
      }
  
      .hljs-string,
      .hljs-symbol,
      .hljs-bullet {
        color: #b9f18d;
      }
  
      .hljs-title,
      .hljs-section {
        color: #faf594;
      }
  
      .hljs-keyword,
      .hljs-selector-tag {
        color: #70cff8;
      }
  
      .hljs-emphasis {
        font-style: italic;
      }
  
      .hljs-strong {
        font-weight: 700;
      }
    }
  }
  
  .tableWrapper {
    overflow-x: auto;
  }
  
  .resize-cursor {
    cursor: ew-resize;
    cursor: col-resize;
  }

  table {
    border-collapse: collapse;
    margin: 0;
    overflow: hidden;
    table-layout: fixed;
    width: 100%;

    td,
    th {
      border: 1px solid var(--gray-3);
      box-sizing: border-box;
      min-width: 1em;
      padding: 6px 8px;
      position: relative;
      vertical-align: top;

      > * {
        margin-bottom: 0;
      }
    }

    th {
      background-color: var(--gray-1);
      font-weight: bold;
      text-align: left;
    }

    .selectedCell:after {
      background: var(--gray-2);
      content: "";
      left: 0; right: 0; top: 0; bottom: 0;
      pointer-events: none;
      position: absolute;
      z-index: 2;
    }

    .column-resize-handle {
      background-color: var(--purple);
      bottom: -2px;
      pointer-events: none;
      position: absolute;
      right: -2px;
      top: 0;
      width: 4px;
    }
  }

  .tableWrapper {
    margin: 1.5rem 0;
    overflow-x: auto;
  }

</style>